#include "../include/sqlpool.h"
#include "../include/log/log.h"

// 构造函数
SqlPool::SqlPool()
    :m_queueSize(8), mutex(0, 1), full(0, m_queueSize), empty(0, 0), isClose(false){
    for( int i = 0; i < m_queueSize; ++i){
        // 调用mysql_init函数为mysql连接分配一个内存空间
        MYSQLPTR conn = mysql_init(nullptr);
        // 调用mysql_real_connect将mysql连接保存在申请得到的内存空间内
        MYSQLPTR p = mysql_real_connect(conn, svr.c_str(), usr.c_str(), pwd.c_str(), db.c_str(), 3306, nullptr, 0);
        if(p == nullptr){
            LOG_WARN("mysql连接失败");
            isClose = true;
        }
        else{ 
            m_sqlQueue.push(conn);
        }
    }
    
}

SqlPool *SqlPool::obj = new SqlPool();
//单例函数
SqlPool *SqlPool::getInstance(){
    return obj;
}
// // 初始化函数，并将mysql连接初始化好
// void SqlPool::_init(const std::string &svr, 
//                const std::string &usr,
//                const std::string &pwd,
//                const std::string &db,
//                const std::string &port){
//     for(int i = 0; i < m_queueSize; ++i){
//         MYSQLPTR conn = mysql_init(nullptr);
//         MYSQLPTR p = mysql_real_connect(conn, svr.c_str(), usr.c_str(), pwd.c_str(), db.c_str(), 3306, nullptr, 0);
//         if(p == nullptr){
//             LOG_WARN("mysql连接失败");
//             return;
//         }
//         m_sqlQueue.push(conn);
//     }
// }
//获取连接
MYSQLPTR SqlPool::getConn(){
    // 上锁
    MYSQLPTR conn = nullptr;
    if(!isClose){
        full.wait();
        mutex.wait();

        conn = m_sqlQueue.front();
        m_sqlQueue.pop();

        mutex.post();
        empty.post();
    }
    return conn;
}
// 归还连接
void SqlPool::freeConn(MYSQLPTR connPtr){
    // 上锁
    if(!isClose){
        empty.wait();
        mutex.wait();

        m_sqlQueue.push(connPtr);
        
        mutex.post();
        full.post();
    }
    else{
        // 外部调用想归还SQL连接，但是连接池已经是处于关闭状态
        mysql_close(connPtr); // 直接调用api释放连接。但是这个函数还有时间执行吗？这是个问题。
    }
}

// 析构函数
SqlPool::~SqlPool(){
    isClose = true;
    mutex.wait();
    while(!m_sqlQueue.empty()){
        mysql_close(m_sqlQueue.front());
        m_sqlQueue.pop();
    }
    mutex.post();
}